package com.drcoffee.drcoffeemall.util;

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.drcoffee.drcoffeemall.entry.Result;
import com.drcoffee.drcoffeemall.mapper.AttachmentMapper;
import com.drcoffee.drcoffeemall.service.impl.AttachmentServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

/*
 * aliyun OSS对象存储
 * */
@Slf4j
@Component
public class OSSUtil {

    @Value("${oss_config.accessKeyId}")
    private String accessKeyId;

    @Value("${oss_config.accessKeySecret}")
    private String accessKeySecret;

    @Value("${oss_config.endpoint}")
    private String endpoint;

    @Value("${oss_config.bucketName}")
    private String bucketName;

    @Autowired
    AttachmentMapper attachmentMapper;

    /*
     * 上传文件
     * */
    public Result upload(MultipartFile file, String file_path, String file_name) {
        OSS ossClient = null;
        try {
            // 检查文件大小
            long maxSize = 5 * 1024 * 1024; // 5MB
            if (file.getSize() > maxSize) {
                // 文件大小不能超过5MB
                return new Result(2, "SUCCESS", "The file size cannot exceed 5MB", null);
            }

            // 获取当前时间戳
            long timestamp = System.currentTimeMillis();

            // 格式化时间戳为字符串
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String formattedTimestamp = sdf.format(new Date(timestamp));

            // 文件名
            file_name = "/" + formattedTimestamp + "_" + UUID.randomUUID() + "_" + file_name;
            CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
            ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
            System.out.println(file_path + file_name);
            ossClient.putObject(bucketName, file_path + file_name, new ByteArrayInputStream(file.getBytes()));
            return new Result(1, "SUCCESS", "", file_name);
        } catch (Exception e) {
            log.error("===================== upload()异常： =====================", e);
            return new Result(-1, "ERROR", e.getMessage(), null);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /*
     * 上传文件
     * */
    public Result uploadFileList(MultipartFile[] files, String file_path) {
        List<Result> results = new ArrayList<>();
        OSS ossClient = null;
        try {
            for (MultipartFile file : files) {
                if (file.getSize() > 5 * 1024 * 1024) {
                    // 文件大小不能超过5MB
                    results.add(new Result(2, "ERROR", "The file size of " + file.getOriginalFilename() + " exceeds 5MB.", null));
                    continue;
                }
                // 文件类型检查，这里仅检查图像类型
                String contentType = file.getContentType();
                if (!contentType.startsWith("image/")) {
                    results.add(new Result(2, "ERROR", "Only image files are allowed for " + file.getOriginalFilename(), null));
                    continue;
                }

                // 获取当前时间戳
                long timestamp = System.currentTimeMillis();

                // 格式化时间戳为字符串
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                String formattedTimestamp = sdf.format(new Date(timestamp));

                // 图片文件名，添加随机字符串以避免文件名冲突
                String file_name = formattedTimestamp + "_" + UUID.randomUUID() + "_" + file.getOriginalFilename();

                CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
                ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
                ossClient.putObject(bucketName, file_path + file_name, new ByteArrayInputStream(file.getBytes()));

                results.add(new Result(1, "SUCCESS", "File uploaded successfully: " + file_name, file_name));
            }

            return new Result(1, "SUCCESS", " ", results);
        } catch (OSSException | ClientException e) {
            log.error("===================== uploadFileList()异常： =====================", e);
            return new Result(-1, "ERROR", "Error during file upload: " + e.getMessage(), null);
        } catch (Exception e) {
            log.error("===================== uploadFileList()异常： =====================", e);
            return new Result(-1, "ERROR", "Unknown error: " + e.getMessage(), null);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    /*
     * 下载文件
     * */
    public Object download(String file_path) {
        System.out.println(file_path);
        OSS ossClient = null;
        try {
            CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
            ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
            // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
            OSSObject ossObject = ossClient.getObject(bucketName, file_path);
            System.out.println(ossObject);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Length", String.valueOf(ossObject.getObjectMetadata().getContentLength()));
            headers.add("Content-Type", ossObject.getObjectMetadata().getContentType());

            // 读取文件内容到字节数组
            InputStream inputStream = ossObject.getObjectContent();
            byte[] fileBytes = IOUtils.toByteArray(inputStream);
            inputStream.close();
            // 返回ResponseEntity对象
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(fileBytes);
        } catch (Exception e) {
            log.error("===================== download()异常： =====================", e);
            return new Result(-1, "ERROR", e.getMessage(), null);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /*
     * 删除文件
     * */
    public Object deleteFile(String file_path) {
        OSS ossClient = null;
        try {
            CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
            ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
            ossClient.deleteObject(bucketName, file_path);
            return new Result(1, "SUCCESS", "", null);
        } catch (Exception e) {
            log.error("===================== deleteFile()异常： =====================", e);
            return new Result(-1, "ERROR", e.getMessage(), null);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public Map<String, Object> uploadImgPart(MultipartFile file, String filepath, String file_name) throws IOException {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", -1);

        if (file.isEmpty()) {
            resultMap.put("msg", "文件参数 'file' 的值为空！");
            return resultMap;
        }

        String originalFilename = StringUtils.cleanPath(file.getOriginalFilename());
        String fileExtension = StringUtils.getFilenameExtension(originalFilename);

        if (!isValidImageFormat(fileExtension)) {
            resultMap.put("msg", "图片格式错误");
            return resultMap;
        }

        String formattedTimestamp = generateFormattedTimestamp();
        String fileName = "/image_" + formattedTimestamp + "_" + file_name;

        BufferedImage image = ImageIO.read(new ByteArrayInputStream(file.getBytes()));
        int wh = Math.max(image.getWidth(), image.getHeight()) - 1;
        BufferedImage scaledImage = resizeImage(file, wh, wh); // Specify the desired width and height

        String localPath = "E:\\tmp_image.png"; // 临时存储图片
        File outputFile = new File(localPath);
        ImageIO.write(scaledImage, "jpg", outputFile);

        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
        OSS ossClient = null;

        ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
        System.out.println(filepath + fileName);
        ossClient.putObject(bucketName, filepath + fileName, new ByteArrayInputStream(Files.readAllBytes(Paths.get(localPath))));
        resultMap.put("code", 1);
        resultMap.put("file_path", fileName);
        return resultMap;
    }

    public Map<String, Object> uploadImgPartTmp(MultipartFile file) throws IOException {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", -1);

        if (file.isEmpty()) {
            resultMap.put("msg", "文件参数 'file' 的值为空！");
            return resultMap;
        }

        String originalFilename = StringUtils.cleanPath(file.getOriginalFilename());
        String fileExtension = StringUtils.getFilenameExtension(originalFilename);

        if (!isValidImageFormat(fileExtension)) {
            resultMap.put("msg", "图片格式错误");
            return resultMap;
        }

        String formattedTimestamp = generateFormattedTimestamp();
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(file.getBytes()));
        int wh = Math.max(image.getWidth(), image.getHeight()) - 1;
        BufferedImage scaledImage = resizeImage(file, wh, wh); // Specify the desired width and height

        String localPath = "E:\\tmp_image.png"; // 临时存储图片
        File outputFile = new File(localPath);
        ImageIO.write(scaledImage, "jpg", outputFile);
        resultMap.put("code", 1);
        return resultMap;
    }

    private static boolean isValidImageFormat(String fileExtension) {
        return Arrays.asList("png", "jpg", "jpeg", "wdp").contains(fileExtension.toLowerCase());
    }

    private static String generateFormattedTimestamp() {
        long timestamp = System.currentTimeMillis();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(new Date(timestamp));
    }

    private static BufferedImage resizeImage(MultipartFile file, int width, int height) throws IOException {
        BufferedImage bufferedImage = ImageIO.read(file.getInputStream());

        int scaledWidth, scaledHeight;
        if (bufferedImage.getWidth() > bufferedImage.getHeight()) {
            scaledWidth = width;
            scaledHeight = (width * bufferedImage.getHeight()) / bufferedImage.getWidth();
        } else {
            scaledHeight = height;
            scaledWidth = (height * bufferedImage.getWidth()) / bufferedImage.getHeight();
        }

        Image scaledImage = bufferedImage.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = resizedImage.createGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);

        if (width == scaledImage.getWidth(null))
            g.drawImage(scaledImage, 0, (height - scaledImage.getHeight(null)) / 2, scaledImage.getWidth(null), scaledImage.getHeight(null), Color.white, null);
        else
            g.drawImage(scaledImage, (width - scaledImage.getWidth(null)) / 2, 0, scaledImage.getWidth(null), scaledImage.getHeight(null), Color.white, null);

        g.dispose();

        return resizedImage;
    }


    public static List<String> fileEnumeration() {
        // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
        String endpoint = "https://oss-accelerate.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        CredentialsProvider credentialsProvider = new DefaultCredentialProvider("LTAI5t93UGXDqyiWDdAGAbfw", "l3uTcGlGqZ310P91HaWMBO7p4DhYgm");
        // 填写Bucket名称，例如examplebucket。
        String bucketName = "dmall-dr-coffee";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            // 构造ListObjectsRequest请求。
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
            // 设置prefix参数来获取fun目录下的所有文件。
            listObjectsRequest.setPrefix("PartsMallFile/parts");
            listObjectsRequest.setMaxKeys(1000);
            // 递归列举fun目录下的所有文件。
            ObjectListing listing = ossClient.listObjects(listObjectsRequest);
            List fileNames = new ArrayList<>();
            // 遍历所有文件。
            System.out.println("Objects:");
            for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
//                System.out.println(objectSummary.toString());
//                System.out.println(objectSummary.getKey());
                fileNames.add(objectSummary.getKey());
            }
            System.out.println(fileNames.size());

            // 遍历所有commonPrefix。
            System.out.println("\nCommonPrefixes:");
            for (String commonPrefix : listing.getCommonPrefixes()) {
                System.out.println(commonPrefix);
            }
            return fileNames;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            return null;
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
